/*
 * HostAddr.cpp
 *
 *  Created on: 2016年9月22日
 *      Author: zhengboyuan
 */

#include "HostAddr.h"

#include <string.h>
#include <stdio.h>

#ifdef WIN32
	#include <winsock2.h>
#else
	#include <unistd.h>
	#include <netdb.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>

	#include <sys/types.h>
	#include <ifaddrs.h>
	#include <iconv.h>

#endif //


namespace util
{


HostAddr::HostAddr()
{
}

HostAddr::~HostAddr()
{
}


std::string HostAddr::getHostAddr()
{
	std::string ip;

	char hname[1024];
	int rc = gethostname(hname, sizeof(hname));
	if (rc != 0)
	{
		return ip;
	}

	struct hostent *hostEnt = gethostbyname(hname);
	if (hostEnt == NULL)
	{
		return ip;
	}

	for (int i = 0; hostEnt->h_addr_list[i]; i++)
	{
		struct in_addr* addr = (struct in_addr*) hostEnt->h_addr_list[i];
		std::string str = inet_ntoa(*addr);
		if (str != "127.0.0.1")
		{
			ip = str;
			break;
		}
	}

	if (ip == "127.0.0.1")
	{
		StringArray arr = getHostAddrs();
		if (arr.size() > 0)
		{
			ip = arr[0];
		}
	}

	return ip;
}

HostAddr::StringArray HostAddr::getHostAddrs()
{
	HostAddr::StringArray arr;
#ifdef WIN32
	char hname[1024];
	int rc = gethostname(hname, sizeof(hname));
	if (rc != 0)
	{
		return arr;
	}

	struct hostent *hostEnt = gethostbyname(hname);
	if (hostEnt == NULL)
	{
		return arr;
	}

	for (int i = 0; hostEnt->h_addr_list[i]; i++)
	{
		struct in_addr* addr = (struct in_addr*) hostEnt->h_addr_list[i];
		std::string str = inet_ntoa(*addr);
		if (str != "127.0.0.1")
		{
			arr.push_back(str);
		}
	}
#else
	struct ifaddrs * ifAddrStruct=NULL;
	void * tmpAddrPtr=NULL;

	getifaddrs(&ifAddrStruct);

	while (ifAddrStruct!=NULL)
	{
		if (ifAddrStruct->ifa_addr->sa_family == AF_INET) { // check it is IP4
			// is a valid IP4 Address
			tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
			char addressBuffer[INET_ADDRSTRLEN];
			inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
            if (strcmp("lo", ifAddrStruct->ifa_name) != 0)
            {
			    //printf("%s IP Address %s/n", ifAddrStruct->ifa_name, addressBuffer);
            	arr.push_back(addressBuffer);
            }
		}
		else if (ifAddrStruct->ifa_addr->sa_family==AF_INET6)
		{ // check it is IP6
			// is a valid IP6 Address
			tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
			char addressBuffer[INET6_ADDRSTRLEN];
			inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
			//printf("%s IP Address %s/n", ifAddrStruct->ifa_name, addressBuffer);
			//ip = addressBuffer;
			//break;
		}
		ifAddrStruct=ifAddrStruct->ifa_next;
	}
#endif //WIN32

	return arr;
}






} /* namespace util */
